package top.frsf.mqtt.session;

import io.netty.channel.Channel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.springframework.stereotype.Component;
import top.frsf.dashboard.pojo.vo.ClientVO;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 会话管理器
 *
 * @author He Kuntao
 * @since 2025/5/28 15:11
 */
@Component
public class SessionManager {

    /**
     * 客户端连接 clientId -> channel
     */
    private final Map<String, ClientVO> clients = new ConcurrentHashMap<>();
    /**
     * 订阅关系 topic -> [clientId1, clientId...]
     */
    private final Map<String, Set<String>> topicSubscribers = new ConcurrentHashMap<>();

    /**
     * 获取客户端管道
     *
     * @param clientId 客户端ID
     * @return 通信管道
     */
    public Channel getChannelByClientId(String clientId) {
        return clients.get(clientId).getChannel();
    }

    /**
     * 获取客户端ID
     *
     * @param channel 通信管道
     * @return 客户端ID
     */
    public String getClientIdByChannel(Channel channel) {
        for (Map.Entry<String, ClientVO> entry : clients.entrySet()) {
            if (entry.getValue().getChannel() == channel) {
                return entry.getKey();
            }
        }
        return null;
    }

    /**
     * 获取所有客户端ClientID
     *
     * @return 客户端ID集合
     */
    public Set<String> getClients() {
        return clients.keySet();
    }

    /**
     * 添加客户端连接
     *
     * @param clientId 客户端ID
     * @param channel  通信管道
     */
    public void addClient(String clientId, NioSocketChannel channel) {
        clients.put(clientId, ClientVO.builder()
                .clientId(clientId)
                .connected(channel.isActive())
                .connectTime(LocalDateTime.now())
                .ip(channel.remoteAddress().getAddress().getHostAddress())
                .port(channel.remoteAddress().getPort())
                .channel(channel)
                .build());
    }

    /**
     * 删除客户端连接
     *
     * @param clientId 客户端ID
     */
    public void removeClient(String clientId) {
        clients.remove(clientId);
    }


    /**
     * 添加订阅关系
     *
     * @param topic    主题
     * @param clientId 客户端ID
     */
    public void addSubscription(String topic, String clientId) {
        topicSubscribers.computeIfAbsent(topic, k -> new HashSet<>()).add(clientId);
    }

    /**
     * 删除订阅关系
     *
     * @param topic    主题
     * @param clientId 客户端ID
     */
    public void removeSubscription(String topic, String clientId) {
        Set<String> subscribers = topicSubscribers.get(topic);
        if (subscribers != null) {
            subscribers.remove(clientId);
            if (subscribers.isEmpty()) {
                topicSubscribers.remove(topic);
            }
        }
    }

    /**
     * 获取订阅关系
     *
     * @param topic 主题
     * @return 订阅关系
     */
    public Set<String> getSubscribers(String topic) {
        return topicSubscribers.getOrDefault(topic, Collections.emptySet());
    }

    /**
     * 获取订阅关系数量
     *
     * @return 订阅关系数量
     */
    public int getSubscriberCount() {
        return topicSubscribers.size();
    }

    /**
     * 获取所有客户端信息
     *
     * @return 所有客户端信息
     */
    public Collection<ClientVO> getClientInfos() {
        return clients.values();
    }
}
